package server;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import common.Logger;
import common.Message;
import common.MessageType;

public class RoomManager implements Serializable {
	
	private static final long serialVersionUID = 3060030678972895172L;
	
	private HashMap<Integer, HashSet<String>> roomMap;
	private static RoomManager instance;
	private int roomID;
	private static Server serv;
	
	private static Logger log = null;
	
	static void setServer(Server s) {
		RoomManager.serv = s;
	}
	
	private RoomManager() {
		
		roomMap = new HashMap<Integer, HashSet<String>>();
		roomID = 0;
	}
	
	static RoomManager getInstance(Logger l) {
		
		if (RoomManager.instance == null)
			RoomManager.instance = new RoomManager();
		
		log = l;
		
		return RoomManager.instance;
	}
	
	synchronized int addRoom() {
		
		int id = generateID();
		roomMap.put(id, new HashSet<String>());
		
		log.log("RoomManager: new room with id " + id);
		
		//roomMap.get(id).add(name);
		//System.out.println("add room " + id + " " + name + " " + roomMap.get(id).size());
		return id;
	}
	
	synchronized void addClientToRoom(int id, String name) {
		
		if (roomMap.get(id).contains(name))
			return;
		
		roomMap.get(id).add(name);
		
		System.out.println("addclient room " + id + " " + name + " " + roomMap.get(id).size());
		
		ClientService cs = getClientService(name);
		
		if (cs != null) {
			cs.send(new Message(MessageType.ROOM_INVITATION, String.valueOf(id)));
		}
		
		updateMembers(id);
	}
	
	synchronized void removeClientFromRoom(int id, String name) {
		
		roomMap.get(id).remove(name);
		if (roomMap.get(id).size() == 0)
			roomMap.remove(id);
		else {
			updateMembers(id);
		}
	} 
	
	synchronized void sendMessage(String who, int rID, String msg, ArrayList<String> list) {
		
		System.out.println("sendM " + who + " " + rID + " " + msg);
		
		ClientService cs;
		
		for (String s : roomMap.get(rID)) {
			System.out.println(s);
			if (!s.equals(who)) {
				
				cs = getClientService(s);
			
				if (cs != null) {
					cs.send(new Message(MessageType.MESSAGE, msg, list, who, rID));
				}
			}
		}
	}
	
	private int generateID() {
		
		return ++roomID; 
	}
	
	private ClientService getClientService(String name) {

		HashMap<ClientService, String> clients = serv.getClients();
		
		for (Map.Entry<ClientService, String> e : clients.entrySet())
		{
			if (name.equals(e.getValue())) {
				return e.getKey();
			}
		}
		
		return null;
	}
	
	private void updateMembers(int rID) {

		ClientService cs;
		
		for (String s : roomMap.get(rID)) {
					
			cs = getClientService(s);
		
			if (cs != null) {
				cs.send(new Message(MessageType.MEMBERS_UPDATE, null, new ArrayList<String>(roomMap.get(rID)) , null, rID));
			}
			
		}
	}
}
